import { inject, onMounted } from 'vue'
import './comps.scss'

// 事件过滤，有些重复的事件只执行一次
function eventConflictFilter(evs = [], name) {
  if (evs.includes('onChange') && name === 'onClear') {
    return true
  }
}
// 组合select选择方式
function multipleFunc(type) {
  if (!type) {
    return
  }
  let obj = {
    multiple: true,
  }
  switch (type) {
    case 'normal':
      break
    case 'ct':
      obj.collapseTags = true
      break
    case 'ctt':
      obj.collapseTags = true
      obj.collapseTagsTooltip = true
      break
  }
  return obj
}

export default (props, { slots }) => {
  const { item, form } = props
  // 注入请求方式每个项目的请求api不同
  const api = inject('api')

  function basicWrap(Dom) {
    return <Dom v-model={form[item.model]} clearable={item.clearable} disabled={item.disabled} readonly={item.readonly} placeholder={item.placeholder} />
  }
  // 后处理函数 返回结果递归取值 将'{data:"a.b.c"}'形式的结构，还原成：{data:后台返回需要数据}
  function postHandleFunc(postObj, res) {
    function recursionGet(res, keysStr) {
      let mks = keysStr.split('.')
      let final = res[mks[0]]
      for (let index = 1; index < mks.length; index++) {
        final = final[mks[index]]
      }
      return final
    }
    let result = {}
    for (const key in postObj) {
      result[key] = recursionGet(res, postObj[key])
    }
    return result
  }
  // 事件包装器
  function eventWrap(item, realEventName) {
    return async (e) => {
      let asyncObj = item?.asyncObj
      const { apiUrl, apiMethod = 'GET', modelName = '', selfData = {}, eventTypes, preCallBack, postCallBack, postObj = '' } = item?.asyncObj ?? {}

      // 事件重复过滤 onClear onChange只能触发一种
      if (eventConflictFilter(eventTypes, realEventName)) {
        return
      }
      if (asyncObj && eventTypes?.includes(realEventName)) {
        // 在发出请求之前提供预调用机会
        preCallBack?.()
        // 如果url或者api都没有就别请求了
        if (apiUrl) {
          if (!api) {
            alert('请传递项目中的请求函数')
            return
          }
          // 组装请求data
          let data = { ...selfData }
          // 一般情况下都需要根据input值的结果请求
          if (modelName) {
            data[modelName] = form[item.model]
          }
          let res = await api({
            url: apiUrl,
            method: apiMethod,
            data,
          })
          postCallBack?.(postHandleFunc(postObj, res))
        }
      }
      // 闭包执行，保留item和函数名，触发的时候执行
      item[realEventName]?.(e)
    }
  }

  switch (item.type) {
    case 'input':
      function judgeDom(item) {
        let Dom = <el-input />
        switch (item?.subType) {
          case 'textarea':
            Dom = <el-input type="textarea" rows={item.rows} />
            break
          case 'password':
            Dom = <el-input type="password" showPassword={item.showPassword} />
            break
          case 'number':
            Dom = <el-input-number min={item.min} max={item.max} step={item.step} precision={item.precision} controlsPosition={item.cp} />
            break
        }
        return (
          <Dom
            class="v3-input"
            input-style={item.style}
            maxlength={item.maxlength}
            clearable={item.clearable}
            prefix-icon={item.prefixIcon}
            suffix-icon={item.suffixIcon}
            onInput={eventWrap(item, 'onInput')}
            onClear={eventWrap(item, 'onClear')}
            onBlur={eventWrap(item, 'onBlur')}
            onChange={eventWrap(item, 'onChange')}
          ></Dom>
        )
      }
      return basicWrap(judgeDom(item))
    case 'select':
      return basicWrap(
        <el-select filterable={item.filterable} style={item.style} {...multipleFunc(item.multipleType)}>
          {item.options.map((option) => {
            return (
              // 这个地方需要给option设置格式，需要两层透传，使用react的函数插槽技术
              <el-option label={option.label} value={option.value} disabled={option.disabled}>
                {slots[item.model]?.(option)}
              </el-option>
            )
          })}
        </el-select>,
      )
    case 'switch':
      return basicWrap(
        <el-switch
          active-text={item.activeText}
          inactive-text={item.inactiveText}
          inline-prompt={item.inline}
          active-icon={item.activeIcon}
          inactive-icon={item.inactiveIcon}
          style={{ '--el-switch-on-color': item.activeColor, '--el-switch-off-color': item.inactiveColor }}
        />,
      )
    case 'radio':
      function judgeDomType(item, radio) {
        let Dom = <el-radio />
        switch (item?.subType) {
          case 'button':
            Dom = <el-radio-button />
            break
        }
        return (
          //  在垂直展示的时候需要左边框
          <div className={item.direction === 'vertical' && item.border ? 'v3-vertical-border' : 'v3-no-border v3-radio-dom'}>
            <Dom label={radio.label} border={item.border} disabled={radio.disabled} style={radio.style}>
              {radio.name}
            </Dom>
          </div>
        )
      }
      return basicWrap(
        <el-radio-group
          style={item.style}
          className={item.direction === 'vertical' ? 'v3-vertical-flex' : 'v3-horizion-flex'}
          textColor={item.activeTextColor}
          fill={item.activeFill}
          onChange={eventWrap(item, 'onChange')}
        >
          {item.radios.map((radio) => {
            return judgeDomType(item, radio)
          })}
        </el-radio-group>,
      )
    case 'datePicker':
      return basicWrap(
        <el-date-picker
          type={item.subType || 'date'}
          range-separator={item.separator}
          start-placeholder={item.splaceholder}
          end-placeholder={item.eplaceholder}
          disabled-date={item.disabledDate}
          format={item.format}
          value-format={item.valueFormat}
        />,
      )
    case 'slider':
      return basicWrap(
        <el-slider />
      )
  }
}
